#include <reg52.h>
#include <intrins.h>
//intrins.h函数，一般出现在C51单片机编程中，一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_等时使用

typedef unsigned char uchar;
typedef unsigned int uint;
uchar code table[] = {
	0x3F, //"0"
	0x06, //"1"
	0x5B, //"2"
	0x4F, //"3"
	0x66, //"4"
	0x6D, //"5"
	0x7D, //"6"
	0x07, //"7"
	0x7F, //"8"
	0x6F, //"9"
	0x77, //"A"
	0x7C, //"B"
	0x39, //"C"
	0x5E, //"D"
	0x79, //"E"
	0x71, //"F"
	0x76, //"H"
	0x38, //"L"
	0x37, //"n"
	0x3E, //"u"
	0x73, //"P"
	0x5C, //"o"
	0x40, //"-"
	0x00  //熄灭
};
// void delay(uchar i)
// {
// 	while (i--)
// 		;
// }
void delay(int s)
{
	uint i, j;
	for (i = 0; i < s; i++) //延时函数
		for (j = 114; j > 0; j--)
			;
}
/**********函数声明********************/
void SendTo595(uchar byteData);
void Hc595SendByte(uchar dat);
/***********************************/

// sbit DS = P3 ^ 4;	 //p3.4串行数据输入   DS
// sbit SH_CP = P3 ^ 6; //串行输入时钟，上升沿有效
// sbit ST_CP = P3 ^ 5; //串行寄存器时钟，上升沿有效

sbit DS = P3 ^ 4;	 //14号引脚，串行数据输入
sbit SH_CP = P3 ^ 6; //11号引脚，移位寄存器时钟输入
sbit ST_CP = P3 ^ 5; //12号引脚，存储寄存器时钟输入

sbit qian = P2 ^ 0;
sbit bai = P2 ^ 1;
sbit shi = P2 ^ 2;
sbit ge = P2 ^ 3;
uchar i = 0;
void main()
{
	TH0 = (65536 - 46080) / 256; //50ms@11.0592MHz
	TL0 = (65536 - 46080) % 256;
	TR0 = 1;
	ET0 = 1;
	EA = 1;
	while (1)
	{
		// qian = 1;
		// bai = 1;
		// shi = 1;
		// ge = 1;
	}
}
void timer0() interrupt 1
{
	TH0 = (65536 - 46080) / 256; //50ms@11.0592MHz
	TL0 = (65536 - 46080) % 256;
	P2 |= 0x0f;
	SendTo595(table[i++]); //二进制:0101 0101
	qian = 0;
	bai = 1;
	shi = 1;
	ge = 1;
	delay(20);
	SendTo595(table[i++]); //二进制:0101 0101
	qian = 1;
	bai = 0;
	shi = 1;
	ge = 1;
	delay(20);
	SendTo595(table[i++]); //二进制:0101 0101
	qian = 1;
	bai = 1;
	shi = 0;
	ge = 1;
	delay(20);
	SendTo595(table[i++]); //二进制:0101 0101
	qian = 1;
	bai = 1;
	shi = 1;
	ge = 0;
	delay(20);
	if (i > 8)
		i = 0;
}
//发送一个字节数据给595再并行输出
void SendTo595(uchar Data)
{
	char i = 0;
	for (i; i < 8; i++)
	{
		SH_CP = 0;				//先拉低，为后面的上升沿做准备
		DS = 0x80 & Data;		//&为按位运算符，即全1为1，有0为0，上式也就是 （1000 0000）&（1111 1111）=1000 0000，若高位为1则是1高位为0则这个式子为0
		Data = _crol_(Data, 1); //左移一位 将高位补给低位，如果二进制数为01010101 那么_crol_(1) 为10101010
		SH_CP = 1;				//上升沿让串行输入时钟变成高电平 并延时一个时钟周期
		_nop_();
	}
	/*位移寄存器完毕，转移到存储寄存器*/
	ST_CP = 1; //上升沿，存储寄存器变为高电平 延迟两个时钟周期
	_nop_();
	_nop_();
	ST_CP = 0;
}

void Hc595SendByte(uchar dat)
{
	int i;	   //编译可能有点老，变量的定义必须放在块的开头
	SH_CP = 0; //初始化
	ST_CP = 0;
	for (i = 0; i < 8; i++) //从高位到低位，依次串行输入
	{
		DS = dat >> 7;
		dat <<= 1;
		SH_CP = 1; //上升沿，将数据串行输入
		_nop_();   //一个机器周期
		_nop_();
		SH_CP = 0;
	}
	ST_CP = 1; //上升沿，将数据送入存储寄存器
	_nop_();   //一个机器周期
	_nop_();
	ST_CP = 0;
}